package service

import (
	"Gin-Server-01/com/server/core/common"
	"Gin-Server-01/com/server/core/pojo"
	"Gin-Server-01/com/server/core/tools/errs"
	"Gin-Server-01/com/server/core/tools/jsonTool"
	"Gin-Server-01/com/server/core/tools/redisPoolTool"
	"Gin-Server-01/com/server/core/tools/times"
	"fmt"
	"github.com/gorilla/websocket"
	"golang.org/x/net/context"
	"net/http"
	"strings"
	"sync"
	"time"
)

const (
	// Chat Redis行为
	Chat = "Chat"
	// OutBox 发件箱-
	OutBox = ":OutBox_fromID:"
	//fromIDPre 发送者
	fromIDPre = ":fromID:"
	// InBox 收件箱-
	InBox = ":InBox_toID:"
	// toIDPre 接收者
	toIDPre = ":toID:"
	//TODO:发件箱设计规则   Chat:OutBox_fromID:{{fromID}}:toID:{{toID}}
	//TODO:收件箱设计规则   Chat:InBox_toID:{{toID}}:fromID:{{fromID}}
)

// ChatServiceDesign
//
// @Tags ws
// @Summary 设计规则
// @Description 发件箱设计规则 Chat:OutBox_fromID:[[fromID]]:toID:[[toID]];收件箱设计规则 Chat:InBox_toID:[[toID]]:fromID:[[fromID]]
// @Router /chat_design [get]
func ChatServiceDesign() {}

// ChatDeleteService
// @Tags ws
// @Summary 获取消息
// @Description ws协议:根据id获取收件箱消息
// @Param wsObjs body pojo.WsObjs true "用户ID"
// @Router /chat_delete [delete]
func ChatDeleteService(c context.Context, conn *websocket.Conn, wsObjs *pojo.WsObjs) {

}

// ChatGetService
//
// @Tags ws
// @Summary 获取消息
// @Description ws协议:根据id获取收件箱消息
// @Param wsObjs body pojo.WsObjs true "用户ID"
// @Router /chat_get [get]
func ChatGetService(c context.Context, conn *websocket.Conn, wsObjs *pojo.WsObjs) {
	//
	chatPayload := pojo.ChatPayload{}

	formatString := jsonTool.JsonFormatString(wsObjs.Actions.Param)
	jsonTool.JSONToStruct(formatString, &chatPayload)

	//查询redis
	queryRedisKey := strings.Builder{}
	var tempPayloads = []pojo.ChatPayload{}

	queryRedisKey.WriteString(fmt.Sprintf("%s%s%d%s",
		Chat, InBox, chatPayload.ReceiverID, fromIDPre))

	//查询redis的key
	queryRedisKeyStr := queryRedisKey.String()

	hashData, _ := redisPoolTool.HGetAll(queryRedisKeyStr)

	for key, value := range hashData {
		//当key是发送者的标记
		if strings.EqualFold(key, fmt.Sprintf("%d", chatPayload.SenderID)) {
			jsonTool.JSONToStruct(value, &tempPayloads)
		}
	}

	response := common.NewResponse(http.StatusOK, "获取成功", tempPayloads)

	conn.WriteMessage(websocket.TextMessage, []byte(jsonTool.JsonFormatString(response)))
}

// ChatPostService
//
// @Tags ws
// @Summary 发送消息
// @Description ws协议:向某个id发送消息
// @Param wsObjs body pojo.WsObjs true "用户ID" example:{"actions":{"method":"get","url":"chat","param":{"senderID":1,"content":"在不在","receiverID":2}}}
// @Success 200 {object} pojo.WsObjs "发送成功"
// @Router /chat_post [post]
func ChatPostService(c context.Context, conn *websocket.Conn, wsObjs *pojo.WsObjs) {

	//添加锁
	mutex := sync.Mutex{}
	mutex.Lock()
	chatPayload := pojo.ChatPayload{
		Timestamp: times.FormatDateTime(),
		IsRead:    false,
	}

	formatString := jsonTool.JsonFormatString(wsObjs.Actions.Param)
	jsonTool.JSONToStruct(formatString, &chatPayload)

	//todo:非法校验
	if chatPayload.ReceiverID == chatPayload.SenderID {
		response := common.NewResponse(http.StatusMethodNotAllowed, "自己无法给自己发送", "")
		conn.WriteMessage(websocket.TextMessage, []byte(jsonTool.JsonFormatString(response)))

		return
	}

	//

	//过期时间
	expiration := time.Second * 20000

	//TODO:站在发送者角度-执行
	builder := strings.Builder{}
	builder.WriteString(fmt.Sprintf("%s%s%d%s",
		Chat, OutBox, chatPayload.SenderID, toIDPre))

	queryRedisKey := builder.String()
	//插入数据
	insertList := []pojo.ChatPayload{}
	temoPayload := pojo.ChatPayload{}
	temoPayloads := []pojo.ChatPayload{}

	//在插入之前查询
	hashData, _ := redisPoolTool.HGetAll(queryRedisKey)

	if len(hashData) != 0 {
		//遍历
		for key, value := range hashData {
			if strings.EqualFold(key, fmt.Sprintf("%d", chatPayload.ReceiverID)) {
				jsonTool.JSONToStruct(value, &temoPayloads)
			}

		}
		insertList = temoPayloads

		for _, obj := range hashData {
			jsonTool.JSONToStruct(jsonTool.JsonFormatString(obj), &temoPayload)
			insertList = append(insertList, chatPayload)
		}
	} else {
		insertList = append(insertList, chatPayload)
	}

	//追加插入
	_, err := redisPoolTool.HSetWithExpiration(queryRedisKey, fmt.Sprintf("%d", chatPayload.ReceiverID), jsonTool.JsonFormatString(insertList), expiration)
	errs.HandleErrorsByMsg(err, "")

	//========================
	builder.Reset()
	builder = strings.Builder{}
	//========================
	//TODO:站在接收者角度-执行
	//设置key
	builder.WriteString(fmt.Sprintf("%s%s%d%s",
		Chat, InBox, chatPayload.ReceiverID, fromIDPre))
	queryRedisKey = builder.String()

	//插入数据
	insertList = []pojo.ChatPayload{}
	temoPayload = pojo.ChatPayload{}
	//在插入之前查询
	hashData, _ = redisPoolTool.HGetAll(queryRedisKey)

	//如过不为空--追加插入
	if len(hashData) != 0 {
		//遍历
		for key, value := range hashData {
			if strings.EqualFold(key, fmt.Sprintf("%d", chatPayload.SenderID)) {
				jsonTool.JSONToStruct(value, &temoPayloads)
			}
		}
		insertList = temoPayloads

		for _, obj := range hashData {
			jsonTool.JSONToStruct(jsonTool.JsonFormatString(obj), &temoPayload)
			insertList = append(insertList, chatPayload)
		}
	} else {
		insertList = append(insertList, chatPayload)
	}

	_, err = redisPoolTool.HSetWithExpiration(queryRedisKey, fmt.Sprintf("%d", chatPayload.SenderID), jsonTool.JsonFormatString(insertList), expiration)
	errs.HandleErrorsByMsg(err, "")

	//返回
	response := common.NewResponse(http.StatusOK, "发送成功", nil)
	conn.WriteMessage(websocket.TextMessage, []byte(jsonTool.JsonFormatString(response)))

	//解锁
	mutex.Unlock()

}
